﻿using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Diagnostics;
using System;
using System.IO;

namespace VideoMagic.EffectsLibrary
{
    public class DepthMerge : ShaderEffect
    {
        static DepthMerge()
        {
            // Associate _pixelShader with our compiled pixel shader
            _pixelShader.UriSource = Global.MakePackUri("DepthMerge.cso");
        }

        public DepthMerge()
        {
            //_pixelShader.UriSource = new Uri(Path.Combine(Environment.CurrentDirectory, "DepthMerge.cso"));

            // The inherited property PixelShader must be set
            this.PixelShader = _pixelShader;

            // Force the pixel shader to update all input values
            UpdateShaderValue(ColorBackgroundProperty);
            UpdateShaderValue(ColorInputProperty1);
            UpdateShaderValue(ColorInputProperty2);

            UpdateShaderValue(DepthInputBackgroundProperty);
            UpdateShaderValue(DepthInput1Property);
            UpdateShaderValue(DepthInput2Property);

            UpdateShaderValue(NearDistanceProperty);
            UpdateShaderValue(FarDistanceProperty);
        }

        /// <summary>
        /// Called when each property has been set to a writable bitmap
        /// </summary>
        public bool PropertySetComplete { get; set; }

        // Implicit input
        public Brush ColorBackground
        {
            get { return (Brush)GetValue(ColorBackgroundProperty); }
            set { SetValue(ColorBackgroundProperty, value); }
        }

        // Additional input
        public Brush ColorInput1
        {
            get { return (Brush)GetValue(ColorInputProperty1); }
            set { SetValue(ColorInputProperty1, value); }
        }

        public Brush ColorInput2
        {
            get { return (Brush)GetValue(ColorInputProperty2); }
            set { SetValue(ColorInputProperty2, value); }
        }

        public Brush DepthInputBackground
        {
            get { return (Brush)GetValue(DepthInputBackgroundProperty); }
            set { SetValue(DepthInputBackgroundProperty, value); }
        }

        public Brush DepthInput1
        {
            get { return (Brush)GetValue(DepthInput1Property); }
            set { SetValue(DepthInput1Property, value); }
        }

        public Brush DepthInput2
        {
            get { return (Brush)GetValue(DepthInput2Property); }
            set { SetValue(DepthInput2Property, value); }
        }

        public static readonly DependencyProperty ColorBackgroundProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("ColorBackground", typeof(DepthMerge), 0);
        public static readonly DependencyProperty ColorInputProperty1 = ShaderEffect.RegisterPixelShaderSamplerProperty("ColorInput1", typeof(DepthMerge), 1);
        public static readonly DependencyProperty ColorInputProperty2 = ShaderEffect.RegisterPixelShaderSamplerProperty("ColorInput2", typeof(DepthMerge), 2);

        public static readonly DependencyProperty DepthInputBackgroundProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("DepthBackground", typeof(DepthMerge), 3);
        public static readonly DependencyProperty DepthInput1Property = ShaderEffect.RegisterPixelShaderSamplerProperty("DepthInput1", typeof(DepthMerge), 4);
        public static readonly DependencyProperty DepthInput2Property = ShaderEffect.RegisterPixelShaderSamplerProperty("DepthInput2", typeof(DepthMerge), 5);

        // Custom shader parameter
        public double NearDistance
        {
            get { return (double)GetValue(NearDistanceProperty); }
            set { SetValue(NearDistanceProperty, value); }
        }

        public static readonly DependencyProperty NearDistanceProperty = DependencyProperty.Register("NearDistance", typeof(double), typeof(DepthMerge), new UIPropertyMetadata(0d, PixelShaderConstantCallback(0)));

        // Custom shader parameter
        public int FarDistance
        {
            get { return (int)GetValue(FarDistanceProperty); }
            set { SetValue(FarDistanceProperty, value); }
        }

        public static readonly DependencyProperty FarDistanceProperty = DependencyProperty.Register("FarDistance", typeof(double), typeof(DepthMerge), new UIPropertyMetadata(1d, PixelShaderConstantCallback(1)));



        // Custom shader parameter
        public double TooNear
        {
            get { return (double)GetValue(TooNearProperty); }
            set { SetValue(TooNearProperty, value); }
        }

        public static readonly DependencyProperty TooNearProperty = DependencyProperty.Register("TooNear", typeof(double), typeof(DepthMerge), new UIPropertyMetadata(0d, PixelShaderConstantCallback(0)));

        // Custom shader parameter
        public double TooFar
        {
            get { return (int)GetValue(TooFarProperty); }
            set { SetValue(TooFarProperty, value); }
        }

        public static readonly DependencyProperty TooFarProperty = DependencyProperty.Register("TooFar", typeof(double), typeof(DepthMerge), new UIPropertyMetadata(1d, PixelShaderConstantCallback(1)));

        // Custom shader parameter
        public double UnknownDistance
        {
            get { return (double)GetValue(UnknownDistanceProperty); }
            set { SetValue(UnknownDistanceProperty, value); }
        }

        public static readonly DependencyProperty UnknownDistanceProperty = DependencyProperty.Register("UnknownDistance", typeof(double), typeof(DepthMerge), new UIPropertyMetadata(0d, PixelShaderConstantCallback(0)));


        // One instance of the compiled shader is enough for the whole class
        private static PixelShader _pixelShader = new PixelShader();
    }
}
